﻿#region Header

/*
Behavioral Rating of Dancing Human Crowds based on Motion Patterns
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using Emgu.CV;
using Emgu.CV.Structure;
using paravili.Services;
using Sebarf.Services.Interfaces;

#endregion

namespace paravili.Steps {
	/// <summary>
	/// Limits the rgb values to the given parameters
	/// </summary>
	public class AvoidExtremRGBValues : ProcessStepWithMeasurement<Image<Bgr, Byte>> {
		# region Public Properties

		public Image<Lab, Byte> LastImage { get; private set; }

		[ServiceRequest]
		public IResetHandlerService ResetHandlerService {
			set { value.Reset += OnReset; }
		}

		[ConfigurableNumericValue(Name = "Max blue value of the lab value", RangeFrom = 1, RangeTo = 255)]
		public int MaxXValue { get; set; }

		[ConfigurableNumericValue(Name = "Max green value of the lab value", RangeFrom = 1, RangeTo = 255)]
		public int MaxYValue { get; set; }

		[ConfigurableNumericValue(Name = "Max red value of the lab value", RangeFrom = 1, RangeTo = 255)]
		public int MaxZValue { get; set; }

		[ConfigurableNumericValue(Name = "Min blue value of the lab value", RangeFrom = 1, RangeTo = 255)]
		public int MinXValue { get; set; }

		[ConfigurableNumericValue(Name = "Min green value of the lab value", RangeFrom = 1, RangeTo = 255)]
		public int MinYValue { get; set; }

		[ConfigurableNumericValue(Name = "Min red value of the lab value", RangeFrom = 1, RangeTo = 255)]
		public int MinZValue { get; set; }

		[ConfigurabelBooleanValue(Name = "Is Enable Remove Colours Intensity")]
		public bool IsEnable { get; set; }

		[ConfigurabelStringValue(Name = "ImageProviderId")]
		public String ImageProviderId { get; set; }

		[ConfigurabelBooleanValue(Name = "ForwardImageToImageProvider")]
		public bool ForwardImageToImageProvider { get; set; }

		[ServiceRequest(IsOptional = true)]
		public IImageProviderService ImageProviderService { get; set; }

		[ConfigurabelBooleanValue(Name = "crop the rgb values to the given limit")]
		public bool CropRGBValues { get; set; }

		[ConfigurabelBooleanValue(Name = "ignore the rgb values which are over the given limit")]
		public bool IgnoreExtremeRGBValues { get; set; }

		[ServiceRequest]
		public IImageValidRegionProvider ImageValidRegionProvider { get; set; }

		#endregion

		#region Public Methods

		public AvoidExtremRGBValues() {
			MaxXValue = 255;
			MaxYValue = 255;
			MaxZValue = 255;
			MinXValue = 1;
			MinZValue = 1;
			MinYValue = 1;
			ImageProviderId = "RemoveColoursIntensityRGB.ImageData";
			ForwardImageToImageProvider = false;
			IsEnable = false;
			IgnoreExtremeRGBValues = true;
		}

		protected override Image<Bgr, byte> OnProcess(Image<Bgr, byte> toProcess) {
			if (toProcess != null && IsEnable) {
				var invalidRegion = ImageValidRegionProvider.InvalidRegionByRowAndColumn;
				Image<Bgr, byte> diff = toProcess;
				byte[, ,] data = diff.Data;
				int rows = diff.Rows;
				int cols = diff.Cols;
				for (int col = 0; col < cols; col++) {
					for (int row = 0; row < rows; row++) {
						byte blueValue = data[row, col, 0];
						byte greenValue = data[row, col, 1];
						byte redValue = data[row, col, 2];
						if (CropRGBValues) {
							data[row, col, 0] = (byte)Math.Max(MinXValue, Math.Min(blueValue, MaxXValue));
							data[row, col, 1] = (byte)Math.Max(MinYValue, Math.Min(greenValue, MaxYValue));
							data[row, col, 2] = (byte)Math.Max(MinZValue, Math.Min(redValue, MaxZValue));
						}
						if (IgnoreExtremeRGBValues) {
							invalidRegion[row, col] = (!((blueValue < MaxXValue && blueValue > MinXValue) &&
														(greenValue < MaxYValue && greenValue > MinYValue) &&
														(redValue < MaxZValue && redValue > MinZValue)));
						}
					}
				}
				if (ForwardImageToImageProvider) {
					ImageProviderService.SetImage(ImageProviderId, toProcess.Convert<Lab, Byte>());
				}
				toProcess = diff;
			}
			return toProcess;
		}

		private void OnReset(Object sender, EventArgs args) {
			LastImage = null;
		}

		#endregion
	}
}